#! /usr/bin/env python
#
"""A collection of small utility functions.

These were mostly ripped out of `rg.py` for readability.
"""
__docformat__ = 'reStructuredText' 


## stdlib imports

import operator
import types


## main content

cpdef lconcat(seqs):
    """Return list concatenation of all sequences in `seqs`.

    Examples::
    
      >>> lconcat([[0]])
      [0]

      >>> lconcat([[0],[1]])
      [0, 1]

      >>> lconcat(['a','b'])
      ['a', 'b']
    """
    result = []
    for seq in seqs:
        result.extend(seq)
    return result


cpdef ltranslate(subst, iterable):
    """Return list of items from a sequence, substituting them as specified.

    First argument `subst` is a dictionary, specifying substitutions
    to be applied.  If an item matches a key of the `subst`
    dictionary, the associated dictionary value is returned instead;
    unless the value is `None`, in which case the item is skipped
    altogether.

    *Note:* you should use an appropriate `dict`-subclass if you want
     to translate items which are not immutable.
    
    Examples::
      >>> ltranslate({0:None, 3:2}, [2,1,0,0,1,3])
      [2, 1, 1, 2]
    """
    translated = []
    for item in iterable:
        try:
            new = subst[item]
            if new is not None:
                translated.append(new)
        except KeyError:
            translated.append(item)
    return translated


cpdef positive_int(arg):
    """Convert a string or number to a positive integer, if possible.
    Behaves just like the built-in `int` (which see), and additionally
    raises `ValueError` if the converted integer is less-then or equal
    to 0.
    """
    result = int(arg)
    if result <= 0:
        raise ValueError("non-positive integer literal: %d" % result)
    return result


cpdef sign(int x):
    """Return the sign of `x`: that is, 0 if `x` is zero, +1 iff it is
    positive, -1 iff it is negative.

    Examples::

      >>> sign(0)
      0
      >>> sign(3)
      1
      >>> sign(-5)
      -1
      
    """
    if x == 0:
        return 0
    elif x == abs(x):
        return +1
    else:
        return -1


## main: run tests

if "__main__" == __name__:
    import doctest
    doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
